#ifndef SERVER_H
#define SERVER_H
//
// server.h
// ~~~~~~~~~~
//
// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//

#include <ctime>
#include <iostream>
#include <string>
#include <boost/bind.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/enable_shared_from_this.hpp>
#include <boost/asio.hpp>

using boost::asio::ip::tcp;
const int inBufferLenMax = 1024 ;
const int portNumber = 35535 ;

typedef void (* FuncRxMsg) ( void * pObject, const char * pBuffer, size_t size) ;
class tcp_server ;

class tcp_connection
  : public boost::enable_shared_from_this<tcp_connection>
{
public:
  typedef boost::shared_ptr<tcp_connection> pointer;

  static pointer create(boost::asio::io_service& io_service, tcp_server & inServer)
  {
    return pointer(new tcp_connection(io_service, inServer));
  }

  tcp::socket& socket()
  {
    return socket_;
  }

  void startRead  () ;
  void receiveMsg (const boost::system::error_code&, size_t) ;
  void writeMsg (std::string & writeMsg ) ;

private:

  tcp_connection(boost::asio::io_service& io_service, tcp_server & inServer)
    : socket_(io_service), server(inServer) 
    {  }

  void handle_write(const boost::system::error_code& /*error*/,
      size_t /*bytes_transferred*/) ;

private:
  tcp::socket socket_;
  char inBuffer[inBufferLenMax+1] ;
   
  tcp_server &server ;
};

class tcp_server
{
public:
  tcp_server(boost::asio::io_service& io_service)
    : acceptor_(io_service, tcp::endpoint(tcp::v4(), portNumber))
  {
    pRxMsg = NULL ;
    pObject = NULL ;
    start_accept();
  }
  
  void receiveMsg ( char *pBuffer, size_t size ) ;
  void writeMsg (std::string & writeMsg ) ;
  void setFuncRxMsg ( void * pInObject, FuncRxMsg * inRxMsg )
  {
      pObject = pInObject ;
      pRxMsg = inRxMsg ;
  }
private:
  void start_accept() ;
  void handle_accept(tcp_connection::pointer new_connection,
      const boost::system::error_code& error) ;

private:
  tcp::acceptor acceptor_;
  
  void * pObject ;
  FuncRxMsg *pRxMsg ;
};

#endif
